package com.shockweb.common.serializable.json;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.shockweb.common.International;
import com.shockweb.common.serializable.SerializableObject;
import com.shockweb.common.utils.classmethod.ClassMethod;
import com.shockweb.common.utils.classmethod.ClassMethodDefine;
/**
 * 通用Json写入器
 * @author: 彭明华
 * History:
 * 2017年5月23日  彭明华创建
 *
 */
public class JsonWriter{


	
	public static final String NULL = "null";
	/**
	 * 构造方法
	 */
	public JsonWriter(){
	}	



	/**
	 * 将value转成xml
	 * @param value 数值
	 * @return String 转义成xml字符串
	 */
    public static final String convertToJson(String value){
    	if(value == null){
    		return null;
    	}else{
    		return value.replaceAll("\"", "\"\"");
    	}
    }

	/**
	 * 格式化成xml合法的字符串
	 * @param v 数值
	 * @param b 转义成json字符串
	 */
	public static final void format(Object v,StringBuilder b) {
		String value = null;
		if(v == null){
			b.append(NULL);
		}else if(v instanceof String){
			value = convertToJson((String)v);
			b.append('\"').append(value).append('\"');
		}else if(v instanceof StringBuilder){
			value = convertToJson(((StringBuilder)v).toString());
			b.append('\"').append(value).append('\"');
		}else if(v instanceof StringBuilder){
			value = convertToJson(((StringBuilder)v).toString());
			b.append('\"').append(value).append('\"');
		}else if(v instanceof Date){
			SimpleDateFormat sdf = new SimpleDateFormat(International.OUT_DATETIME);
			value = sdf.format(v);
			b.append('\"').append(value).append('\"');
		}else if(v instanceof Time){
			SimpleDateFormat sdf = new SimpleDateFormat(International.OUT_TIME);
			value = sdf.format(v);
			b.append('\"').append(value).append('\"');
		}else if(v instanceof Timestamp){
			SimpleDateFormat sdf = new SimpleDateFormat(International.OUT_DATETIMEMSEL);
			value = sdf.format(v);
			b.append('\"').append(value).append('\"');
		}else if(v instanceof java.util.Date){
			SimpleDateFormat sdf = new SimpleDateFormat(International.OUT_DATETIME);
			value = sdf.format(v);
			b.append('\"').append(value).append('\"');
		}else if(v instanceof Character){
			b.append('\"').append((Character)v).append('\"');
		}else if(v.getClass().equals(char.class)){
			b.append('\"').append((Character)v).append('\"');
		}else if(v instanceof BigInteger){
			value = ((BigInteger)v).toString();
			b.append('\"').append(value).append('\"');
		}else if(v instanceof BigDecimal){
			value = ((BigDecimal)v).toString();
			b.append('\"').append(value).append('\"');
		}else if(v instanceof byte[]){
			value = SerializableObject.base64EncodeString((byte[])v);
			b.append('\"').append(value).append('\"');
		}else{
			if(isCustomClass(v.getClass())){
				value = convertToJson(v.toString());
				b.append('\"').append(value).append('\"');
			}else{
				value = v.toString();
				b.append(value);
			}	
		}
	}

	
	
    /**
     * 判断是否用户自定义类
     * @param cls class定义
     * @return boolean 如果是用户自定义类返回true，否则为false
     */
    private static boolean isCustomClass(Class<?> cls){
        if(String.class.equals(cls))
            return false;
        if(StringBuilder.class.equals(cls))
            return false;
        if(BigDecimal.class.equals(cls))
            return false;
        if(double.class.equals(cls) || Double.class.equals(cls))
            return false;
        if(float.class.equals(cls) || Float.class.equals(cls))
            return false;
        if(int.class.equals(cls) || Integer.class.equals(cls))
            return false;
        if(long.class.equals(cls) || Long.class.equals(cls))
            return false;
        if(short.class.equals(cls) || Short.class.equals(cls))
            return false;
        if(boolean.class.equals(cls) || Boolean.class.equals(cls))
            return false;
        if(byte.class.equals(cls) || Byte.class.equals(cls))
            return false;
        if(char.class.equals(cls) || Character.class.equals(cls))
            return false;
        if(Date.class.equals(cls))
            return false;
        if(Time.class.equals(cls))
            return false;
        if(Timestamp.class.equals(cls))
            return false;
        if(java.util.Date.class.equals(cls))
            return false;
        if(boolean.class.equals(cls) || Boolean.class.equals(cls))
            return false;
        if(BigInteger.class.equals(cls))
            return false;
        if(StringBuilder.class.equals(cls))
            return false;
        if(byte[].class.equals(cls))
            return false;
        return true;
    }
    

    
    /**
     * 将对象解析成json写到String中返回
     * @param instance 对象实例
     * @return String
     * @throws JsonException
     */
    public String toJson(Object instance)throws JsonException{
    	StringBuilder rtn = new StringBuilder(4096);
		int startLen = rtn.length();
		try {
			if(instance==null){
				return null;
			}
			if(instance  instanceof List<?>){
				writeList((List<?>)instance,rtn,null);
    		}else if(instance instanceof Map<?,?>){
    			rtn.append('{');
    			writeMap((Map<?,?>)instance,rtn,null);
    			rtn.append('}');
    		}else if(isCustomClass(instance.getClass())){
    			rtn.append('{');
				writeValue(instance,rtn,null);
				rtn.append('}');
			}else{
    			rtn.append("{\"value\":");
    			format(instance,rtn);
    			rtn.append('}');
			}
		} catch (Exception e) {
			throw new JsonException(e);
		}
		if(rtn.length()==startLen){
			return null;
		}
		return rtn.toString();
    }


    /**
     * 将对象instance解析成xml写到StringBuilder中
     * @param instance 普通对象实例
     * @param sb 待写入的StringBuilder
     * @param rootName 根元素名称
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    private void writeValue(Object instance,StringBuilder sb,Object rootName) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException{
    	if(instance!=null){
        	if(isCustomClass(instance.getClass())){
            	List<ClassMethodDefine> cmds = ClassMethod.getGetMethods(instance.getClass());
        		int startLen1 = sb.length();
        		if(rootName!=null){
        			format(rootName,sb);
        			sb.append(":{");
        		}
        		int startLen2 = sb.length();
        		boolean flag = false;
        		for(ClassMethodDefine cmd:cmds){
        			Object value = cmd.getMethod().invoke(instance);
        			if(value!=null){
        				if(!isCustomClass(value.getClass())){
    						sb.append('\"').append(cmd.getName()).append("\":");
    						format(value,sb);
    						sb.append(',');					
        				}else{
        					flag = true;
        				}
        			}else{
						sb.append('\"').append(cmd.getName()).append("\":null,");
        			}
        		}
        		if(flag){		
        			for(ClassMethodDefine cmd:cmds){
        				Object value = cmd.getMethod().invoke(instance);
        				if(value!=null){
        					if(isCustomClass(value.getClass())){
        						if(value instanceof List<?>){
        							writeList((List<?>)value,sb,cmd.getName());
        			    		}else if(value instanceof Map<?,?>){
        			    			writeMap((Map<?,?>)value,sb,cmd.getName());
        						}else{
        							writeValue(value,sb,cmd.getName());
        						}
        						sb.append(',');
        					}
        				}
        			}
        		}
        		if(sb.length()==startLen2){
        			sb.delete(startLen1, sb.length());
        		}else{
        			if(sb.charAt(sb.length()-1)==','){
        				sb.deleteCharAt(sb.length()-1);
        			}
        			if(rootName!=null){
        				sb.append('}');
        			}
        		}
        	}else{
        		if(rootName!=null){
        			sb.append('{');
        			format(rootName,sb);
        			sb.append(':');
        			format(instance,sb);
        			sb.append('}');
        		}else{
        			format(instance,sb);
        		}
        	}
    	}
	}
    
    /**
     * 将List对象lists解析成xml写到StringBuilder中
     * @param lists List对象实例
     * @param sb 待写入的StringBuilder
     * @param rootName 根元素名称
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    private void writeList(List<?> lists,StringBuilder sb,Object rootName) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException{	
		if(rootName!=null){
			format(rootName,sb);
			sb.append(":[");
		}else{
			sb.append('[');
		}
    	for(Object value:lists){
    		if(value instanceof List<?>){
    			writeList((List<?>)value,sb,null);
    			sb.append(',');
    		}else if(value instanceof Map<?,?>){
    			sb.append('{');
    			writeMap((Map<?,?>)value,sb,null);
    			sb.append("},");
    		}else if(isCustomClass(value.getClass())){
    			sb.append('{');
    			writeValue(value,sb,null);
    			sb.append("},");
    		}else{
    			writeValue(value,sb,null);
    			sb.append(',');
    		}
    	}
		if(sb.charAt(sb.length()-1)==','){
			sb.delete(sb.length()-1, sb.length());
		}
		sb.append(']');
		

    }
	
    /**
     * 将map对象maps解析成xml写到StringBuilder中
     * @param maps Map对象实例
     * @param sb 待写入的StringBuilder
     * @param rootName 根元素名称
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    private void writeMap(Map<?,?> maps,StringBuilder sb,Object rootName) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException{	
		if(rootName!=null){
			format(rootName,sb);
			sb.append(":{");
		}
    	Iterator<?> it = maps.keySet().iterator();
    	while(it.hasNext()){
    		Object key = it.next();
    		Object value = maps.get(key);
    		if(value==null){
    			format(key,sb);
    			sb.append(':');
    			format(value,sb);
    		}else if(value instanceof List<?>){
    			writeList((List<?>)value,sb,key);
    		}else if(value instanceof Map<?,?>){
    			writeMap((Map<?,?>)value,sb,key);
    		}else if(isCustomClass(value.getClass())){
    			writeValue(value,sb,key);
    		}else{
    			format(key,sb);
    			sb.append(':');
    			format(value,sb);
    		}
    		sb.append(',');
    	}
		if(sb.charAt(sb.length()-1)==','){
			sb.delete(sb.length()-1, sb.length());
		}
		if(rootName!=null){
			sb.append('}');
		}
    	
    }

}